package com.wangl.spring.declarationHandler;

import com.intellij.codeInsight.navigation.actions.GotoDeclarationHandler;
import com.intellij.lang.properties.IProperty;
import com.intellij.lang.properties.psi.PropertiesFile;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.wangl.spring.service.ProjectSuggestionService;
import com.wangl.spring.suggestion.PropertiesManager;
import com.wangl.spring.utils.PlaceholderResolver;
import com.wangl.spring.utils.PsiCustomUtil;
import org.jetbrains.annotations.Nullable;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @ClassName ValueAnnotationGotoDeclarationHandler
 * @Description TODO
 * @Author wangl
 * @Date 2023/4/26 18:14
 */
public class ValueAnnotationGotoDeclarationHandler implements GotoDeclarationHandler {

    @Override
    public PsiElement @Nullable [] getGotoDeclarationTargets(@Nullable PsiElement source, int offset, Editor editor) {
        Project project = editor.getProject();
        if (project == null){
            return new PsiElement[0];
        }
        PropertiesManager propertiesManager = editor.getProject().getService(ProjectSuggestionService.class).getPropertiesManager();
        if (isAnnotationPsiElement(source)){
            List<String> placeholders = PlaceholderResolver.getPlaceholders(source.getText());
            Module module = PsiCustomUtil.findModule(source);
            Set<PropertiesFile> propertiesFiles = propertiesManager.search(module);
            Map<String, Set<PsiElement>> map = new ConcurrentHashMap<>();
            for (PropertiesFile propertiesFile : propertiesFiles) {
                List<IProperty> properties = propertiesFile.getProperties();
                for (IProperty property : properties) {
                    String key = property.getKey();
                    map.computeIfAbsent(key, k -> new HashSet<>()).add(property.getPsiElement());
                }
            }
            Set<PsiElement> resultSet = new HashSet<>();
            for (String placeholder : placeholders) {
                resultSet.addAll(map.getOrDefault(placeholder, Collections.emptySet()));
            }
            return resultSet.toArray(new PsiElement[0]);
        }
        return new PsiElement[0];
    }

    private boolean isAnnotationPsiElement(PsiElement psiElement){
        PsiElement parent;
        return psiElement instanceof PsiJavaToken &&
                (parent = psiElement.getParent()) instanceof PsiLiteralExpression &&
                (parent = parent.getParent()) instanceof PsiNameValuePair &&
                (parent = parent.getParent()) instanceof PsiAnnotationParameterList &&
                parent.getParent() instanceof PsiAnnotation;
    }
}
